package cmd

import (
	"fmt"
	"os"
	"path/filepath"
	"sync"

	"github.com/spf13/cobra"
)

// downloadCmd represents the download command
var downloadCmd = &cobra.Command{
	Use: "download",
	Short: `download 下载并安装编译器，默认选择开发分支，后可有一个可选的版本号
	示例：
	upam download v0.4.3
	`,
	Long: `download 下载并安装编译器，默认选择开发分支，后可有一个可选的版本号
	示例：
	upam download v0.4.3
	`,
	Run: func(cmd *cobra.Command, args []string) {
		typ := istip(args)
		err := DownloadComplier(cmd, typ)
		if err != nil {
			cmd.PrintErrf("%s\n", err.Error())
		}
	},
}

var u_env_var struct {
	U_HOME          string
	U_Complier_Sdk  string
	U_Complier_Link string
	once            sync.Once
}

func U_HOME_init() {
	u_env_var.once.Do(func() {
		if cc := os.Getenv("U_HOME"); cc != "" {
			u_env_var.U_HOME = cc
		} else {
			//windows的默认U_HOME为%USERPROFILE%\u
			//linux等系统的默认U_HOME为$HOME/u
			hmoe, err := os.UserHomeDir()
			if err != nil {
				fmt.Printf("用户目录获取失败 错误信息%s", err.Error())
				os.Exit(2)
			}
			u_env_var.U_HOME = filepath.Join(hmoe, "u")
		}
		u_env_var.U_Complier_Sdk = filepath.Join(u_env_var.U_HOME, `sdk`)
		u_env_var.U_Complier_Link = filepath.Join(u_env_var.U_Complier_Sdk, `link`)
	})
}

func init() {
	U_HOME_init()
	rootCmd.AddCommand(downloadCmd)
}

// DownloadComplier 下载并源码构建指定版本的编译器
func DownloadComplier(cmd *cobra.Command, typ string) error {
	err := checkVersion(typ) //检查版本号是否正确
	if err != nil {
		return err
	}
	info := GetComplierDirInfo(u_env_var.U_Complier_Sdk) //获取已经下载的编译器信息
	if typ != "tip" && info.Find(typ).Version != "" {    //如果已经下载并安装过
		return fmt.Errorf("版本 %s 已经下载并安装了", typ)
	}
	install := filepath.Join(u_env_var.U_Complier_Sdk, `u@`+typ)
	if typ == "tip" && info.Find(typ).Version != "" { //如果之前安装过tip,并且现在安装tip
		err = os.Chdir(install) //切换工作目录到 $U_HOME+sdk+u@tip
		if err != nil {
			return fmt.Errorf("更改工作目录到 %s 失败 错误信息：%w", install, err)
		}
		err = Exec(cmd, "git", "pull", "--rebase")
		if err != nil {
			return fmt.Errorf("运行git pull --rebase 失败 错误信息：%w", err)
		}
	} else { //如果没有安装过tip
		err = Exec(cmd, "git", "clone", "https://gitee.com/u-language/u-language.git", install)
		if err != nil {
			return fmt.Errorf("运行git clone 失败 错误信息：%w", err)
		}
	}
	var dir string
	beforev0170, err := before017(typ)
	if err != nil {
		return err
	}
	if typ == "tip" || !beforev0170 { //如果是tip或v0.17.0开始的版本
		dir = filepath.Join(install, `ucom`)
	} else { //如果是v0.16.0或更小的版本
		dir = filepath.Join(install, `pkg`)
	}

	err = os.Chdir(dir) //切换工作目录到 $U_HOME+sdk+u@version+ucom
	if err != nil {
		return fmt.Errorf("更改工作目录到 %s 失败 错误信息：%w", dir, err)
	}
	if typ != "tip" { //安装的是指定版本
		err = Exec(cmd, "git", "checkout", typ)
		if err != nil {
			return fmt.Errorf("git checkout %s 失败 错误信息：%w", typ, err)
		}
	}
	err = Exec(cmd, "go", "build", "-o", "ucom"+Ext)
	if err != nil {
		return fmt.Errorf("go build 失败 错误信息：%w", err)
	}
	err = Link(typ)
	return err
}

// ComplierDirInfo 编译器目录信息
type ComplierDirInfo struct {
	// 路径
	Path string
	//编译器版本
	Version string
}

// SortComplierDirInfo 为ComplierDirInfo切片实现 [sort.Interface] 接口
type SortComplierDirInfo []ComplierDirInfo

func (s SortComplierDirInfo) Len() int {
	return len(s)
}

func (s SortComplierDirInfo) Less(i, j int) bool {
	n1minor, n1revised, err := MinorVersionNumberAndRevisedVersionNumber(s[i].Version)
	if err != nil {
		return true
	}
	n2minor, n2revised, err := MinorVersionNumberAndRevisedVersionNumber(s[j].Version)
	if err != nil {
		return false
	}
	if n1minor < n2minor { //如果i的次要版本号更小
		return true
	} else if n1minor > n2minor { //如果i的次要版本号更大
		return false
	}
	return n1revised < n2revised
}

func (s SortComplierDirInfo) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s SortComplierDirInfo) Find(version string) ComplierDirInfo {
	for _, value := range s {
		if value.Version == "u@"+version {
			return value
		}
	}
	return ComplierDirInfo{}
}

// before017 检查是否是v0.17.0之前的版本
func before017(typ string) (bool, error) {
	if typ == "tip" {
		return false, nil
	}
	a, _, err := MinorVersionNumberAndRevisedVersionNumber(typ)
	if err != nil {
		return false, err
	}
	return a <= 16, nil
}
